package pers.chao.logger;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import pers.chao.logger.annotation.ListenerOrder;
import pers.chao.logger.api.AccessLogListener;
import pers.chao.logger.core.aspect.AccessLoggerSupport;
import pers.chao.logger.vo.SortedListener;
import pers.chao.tool.aspect.AopUtil;

/**
 * Description: 访问日志自动配置类
 *
 * @author W.Chao
 * @date 2020/11/15 20:11
 **/
@Configuration
@ComponentScan("pers.chao.logger")
public class AccessLoggerAutoConfigure {

	@Bean
	@ConditionalOnMissingBean(AccessLoggerSupport.class)
	public AccessLoggerSupport aopAccessLoggerSupport() {
		return new AccessLoggerSupport();
	}

	@Bean
	@ConditionalOnMissingBean(ListenerProcessor.class)
	public ListenerProcessor listenerProcessor(AccessLoggerSupport accessLoggerSupport) {
		return new ListenerProcessor(accessLoggerSupport);
	}

	/**
	 * 将监听器添加到切面中
	 */
	public static class ListenerProcessor implements BeanPostProcessor {
		private final AccessLoggerSupport accessLoggerSupport;

		public ListenerProcessor(AccessLoggerSupport accessLoggerSupport) {
			this.accessLoggerSupport = accessLoggerSupport;
		}

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
			return bean;
		}

		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
			if (bean instanceof AccessLogListener) {
				AccessLogListener logListener = (AccessLogListener) bean;
				ListenerOrder listenerOrderAnno = AopUtil.findAnnotation(logListener.getClass(), ListenerOrder.class);
				accessLoggerSupport.addListener(
						new SortedListener(listenerOrderAnno != null ? listenerOrderAnno.value() : 0 /* default */, logListener));
			}
			return bean;
		}
	}
}
